package com.roi.model;

import java.io.*;
import java.util.*;

public class AccController implements Serializable {
	private static final long serialVersionUID = 7671688913698106177L;
	private Scanner scanner;
	private List<Account> accounts;
	private List<Customer> customers;
	public static int count = 10000000;

	public AccController() {
		this.initialise();
	}
	
	//TODO: transfer money, error handling, tests

	private void initialise() {
		this.scanner = new Scanner(System.in);
		this.readData();
		count = accounts.isEmpty() ? count : accounts.get(accounts.size() - 1)
				.getAccountNumber();
		System.out.println(count);
	}

	@SuppressWarnings("unchecked")
	private void readData() {
		try {
			InputStream fis = new FileInputStream(new File(
					"./resources/customers.txt"));
			ObjectInputStream ois = new ObjectInputStream(fis);
			this.customers = (List<Customer>) ois.readObject();
			ois.close();
		} catch (Exception e) {
			System.out.println("customers file not found!");
			this.customers = new ArrayList<>();
		}
		try {
			InputStream fis = new FileInputStream(new File(
					"./resources/accounts.txt"));
			ObjectInputStream ois = new ObjectInputStream(fis);
			this.accounts = (List<Account>) ois.readObject();
			ois.close();
		} catch (Exception e) {
			System.out.println("accounts file not found!");
			this.accounts = new ArrayList<>();
		}
	}

	private void writeData() {
		try {
			FileOutputStream out = new FileOutputStream(new File(
					"./resources/customers.txt"));
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(customers);
			oos.flush();
			oos.close();
		} catch (FileNotFoundException e) {
			System.out.println("file not found: customers");
		} catch (IOException e) {
			System.out.println("cannot write to file: customers");
			e.printStackTrace();
		}
		try {
			FileOutputStream out = new FileOutputStream(new File(
					"./resources/accounts.txt"));
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(accounts);
			oos.flush();
			oos.close();
		} catch (FileNotFoundException e) {
			System.out.println("file not found: accounts");
		} catch (IOException e) {
			System.out.println("cannot write to file: accounts");
		}
	}

	public void start() {
		System.out.println("Please select your option from the menu: "
				+ "\n1) Create customer account"
				+ "\n2) Close customer account"
				+ "\n3) Update customer account" + "\n4) View customer account"
				+ "\n5) Exit");

		int option = scanner.nextInt();
		scanner.nextLine();
		if (option == 1) {
			this.createAccount();
		} else if (option == 2) {
			this.closeAccount();
		} else if (option == 3) {
			this.updateAccount();
		} else if (option == 4) {
			this.displayAccount();
		} else if (option == 5) {
			this.exit();
		}
		this.start();
	}

	private void exit() {
		this.writeData();
		System.exit(0);
	}

	private void updateAccount() {
		if (accounts.isEmpty()) {
			System.out.println("no account in system.");
		} else {
			System.out.println("Enter Account number:");
			int accountNumber = Integer.parseInt(scanner.nextLine());
			for (Account a : accounts) {
				if (accountNumber == a.getAccountNumber()) {
					this.manageAccount(a);
					break;
				}
			}
		}
	}

	public void manageAccount(Account account) {
		System.out.println("Enter option:");
		System.out.println("3.1) Withdraw money");
		System.out.println("3.2) Deposit money");
		System.out.println("3.3) Transfer money");
		String option = scanner.nextLine().trim();

		if (option.equals("3.1")) {
			System.out.print("Enter amount: ");
			double amount = scanner.nextDouble();
			scanner.nextLine();
			account.withdraw(amount);
		} else if (option.equals("3.2")) {
			System.out.print("Enter amount: ");
			double amount = scanner.nextDouble();
			scanner.nextLine();
			account.deposit(amount);
		} else if (option.equals("3.3")) {
			System.out.print("Enter amount: ");
			double amount = scanner.nextDouble();
			scanner.nextLine();
			account.deposit(amount);
		}
	}

	public void createAccount() {
		Customer customer = getCustomer();
		AccountType accType = null;

		System.out.println("Please select account type: " + "\n1) Current"
				+ "\n2) Saving" + "\n3) Credit Card");

		int type = scanner.nextInt();
		switch (type) {
		case 1:
			accType = AccountType.CURRENT;
			break;

		case 2:
			accType = AccountType.SAVING;
			break;

		case 3:
			accType = AccountType.CREDIT;
			break;

		default:
			System.out.println("invalid option!");
			this.createAccount();
			break;
		}

		Account account = openAccount(customer, accType);
		customer.getAccounts().add(account);
		System.out.println(customer);
	}

	public void closeAccount() {
		if (!accounts.isEmpty()) {
			System.out.println("Enter account number to close:");
			int accountNo = Integer.parseInt(scanner.nextLine());
			for (Customer c : customers) {
				for (Account a : c.getAccounts()) {
					if (accountNo == a.getAccountNumber()) {
						for (Account ac : this.accounts) {
							if (a.equals(ac)) {
								accounts.remove(ac);
								System.out
										.println("account deleted from accounts");
							}
							break;
						}
						c.getAccounts().remove(a);
						System.out.println("account deleted from customer");
					}
					if (c.getAccounts().isEmpty()) {
						customers.remove(c);
						System.out.println("customer deleted");
					}
					break;
				}
				break;
			}
		} else {
			System.out.println("no account in system yet.");
		}
	}

	private void displayAccount() {
		if (customers.isEmpty()) {
			System.out.println("No customer yet.");
			System.out.println(accounts.size());
		} else {
			System.out.println("Please type in customer ID number");
			String idNo = scanner.nextLine().trim();
			for (Customer c : customers) {
				if (idNo.equals(c.getIdNo())) {
					System.out.println(c.toString());
					break;
				}
			}
		}
	}

	public Customer getCustomer() {
		System.out.println("Please type in customer ID number: ");
		Customer customer = null;
		String idNo = scanner.nextLine().trim();
		if (!customers.isEmpty()) {
			for (Customer c : customers) {
				if (idNo.equals(c.getIdNo())) {
					customer = c;
					break;
				}
			}
		} else {
			customer = this.createNewCustomer(idNo);
		}
		return customer;
	}

	private Customer createNewCustomer(String idNo) {
		String name = null;
		String address = null;
		String mobNo = null;

		System.out.println("Please type in customer name: ");
		name = scanner.nextLine().trim();
		System.out.println("Please type in first line of address: ");
		address = scanner.nextLine().trim();
		System.out.println("Please type in post code: ");
		address = address + "," + scanner.nextLine().trim();
		System.out.println("Please type in mobile number");
		mobNo = scanner.nextLine();

		Customer customer = new Customer(new ArrayList<Account>(), address,
				name, mobNo, idNo);
		customers.add(customer);
		return customer;
	}

	public Account openAccount(Customer c, AccountType at) {
		count++;
		Account a = at.createAccount(c);
		accounts.add(a);
		return a;
	}

	public static void main(String[] args) {
		new AccController().start();
	}

}
